package model;

import java.util.Collection;


public class Automaton {

	private final StateSet stateSet;
	private final State startState;
	private final TransitionSet transitionSet;

	/**
	 * Constuctor of {@link Automaton}.
	 */
	public Automaton() {
		this.transitionSet = new TransitionSet();
		this.stateSet = new StateSet();
		this.startState = this.createState("z0");
	}
	/**
	 * Returns a {@link RecognizedResult} when the provided String is recognized by this {@link Automaton}.
	 * Else returns a {@link NotRecognizedResult}.
	 * @param string is the String that is tested.
	 * @return a {@link Result} which represents whether the provided String is recognized by this {@link Automaton} or not.
	 */
	public Result recognizes(final String string) {
		final StepperManager manager = new StepperManager(this, string);
		return manager.getResult();
	}

	/**
	 * Provides the start {@link State} of this {@link Automaton}.
	 * @return the start {@link State}.
	 */
	public State getStartState() {
		return this.startState;
	}
	
	/**
	 * Creates a new {@link State} in this {@link Automaton} and returns it.
	 * @param stateName is the name of the new {@link State}.
	 * @return a new {@link State}.
	 */
	public State createState(final String stateName) {
		final State result = new State(stateName);
		this.stateSet.add(result);
		return result;
	}


	/**
	 * Creates a new {@link Transition} from the from {@link State} to the to {@link State} with the provided input and output.
	 * @param from is the from {@link State}.
	 * @param to is the to {@link State}.
	 * @param input is the input of this {@link Transition}
	 * @param output is the output of this {@link Transition}.
	 */
	public void createTransition(final State from, final State to, final char input, final char output) {
		if(!this.stateSet.contains(from)) throw new Error();
		if(!this.stateSet.contains(to)) throw new Error();		
		this.transitionSet.add(new Transition(from,to,input,output));
	}

	/**
	 * Provides a {@link Collection} of all {@link Transition}s that can be reached from the provided from State with the provided input.
	 * @param from is the from {@link State}.
	 * @param input is the input.
	 * @return a {@link Transition} {@link Collection}.
	 */
	public Collection<Transition> getAllFromWith(final State from, final char input){
		return this.transitionSet.getAllFromWith(from, input);
	}
}
